package okna;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.JComboBox;
import javax.swing.DefaultCellEditor;
import javax.swing.table.TableColumn;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;

import dziennik.classes.*;

/**
 * 
 * <p>
 * Klasa dziedziczaca po abstrakcyjnej klasie AbstractTableModel,
 * jest uzywana do konstruckji tabel i przechowywania odpowiednich typow danych.
 * Dane w tabeli przechowywane sa jako tablica dwuwymiarowa typu Object.
 * Oprocz przechowywania specjalnych typow obiektow i odpowiedniego ich wyswietlania,
 * klasa umozliwia:
 * <ul>
 * <li>Edycje wybranej komorki</li>
 * <li>Dodanie kolumny</li>
 * <li>Usuniecie kolumny</li>
 * </ul>
 * </p>
 * 
 * @author Dariusz Orlowski
 *
 */
public class TableModel extends AbstractTableModel {
    private String[] columnNames;
    private Object[][] data;
    private int[] columnSizes;

    //private Dziennik dziennik;
    private int tab;	//0 - oceny, 1 - obecnosci, 2 - uwagi
    private int columns=0;
    private int rows;
    private static Dziennik dziennik;
    private int przedmiot;
	private Calendar calendar = Calendar.getInstance();
    
    /**
	 * <p>
	 * Metoda zwracaja przechowywany obiekt dziennika
	 * </p>
	 * @return Metoda zwracaja przechowywany obiekt dziennika
	 */
    public Dziennik getDziennik(){return dziennik;}

    /**
	 * <p>
	 * Konstruktor klasy. Tworzy model tabeli na podstawie podanych parametrow.
	 * Ustawia dane w komorkach w zaleznosci od typu danych przechowywanych w tabeli.
	 * </p>
	 * @param dz
	 * @param tab
	 * @param przedmiot
	 */
    public TableModel(Dziennik dz, int tab, int przedmiot){
	    super();
	    if (dz!=null) dziennik=dz;
	    this.przedmiot=przedmiot;
	    this.tab=tab;
	
	    	//pobieranie ilosci kolumn
	    if (tab==0){
		    for (int i=0;i<dziennik.getUczen_klasy().size();i++){ 	
		    	if(dziennik.getUczen_klasy().get(i).getPrzedmioty().get(przedmiot).getOceny().size()>columns)
		    	{
		    		int col=dziennik.getUczen_klasy().get(i).getPrzedmioty().get(przedmiot).getOceny().size();
		    		if (col>columns)columns=col;
		    	} 
		    }
	    }
	    else if (tab==1){
		    for (int i=0;i<dziennik.getUczen_klasy().size();i++){ 	
		    	if(dziennik.getUczen_klasy().get(i).getPrzedmioty().get(przedmiot).getObecnosci().size()>columns)
		    	{
		    		int col=dziennik.getUczen_klasy().get(i).getPrzedmioty().get(przedmiot).getObecnosci().size();
		    		if (col>columns)columns=col;
		    	} 
		    }
	    }
	    else if (tab==2){
		    for (int i=0;i<dziennik.getUczen_klasy().size();i++){ 	
		    	if(dziennik.getUczen_klasy().get(i).getUwagi().size()>columns)
		    	{
		    		int col=dziennik.getUczen_klasy().get(i).getUwagi().size();
		    		if (col>columns)columns=col;
		    	} 
		    }
	    }
	    
	    this.rows=this.dziennik.getUczen_klasy().size();
	    this.data=new Object[rows][columns+3];
	    this.columnNames=new String[columns+3];
	    
	    columnNames[0]="ID";
	    columnNames[1]="Imie";
	    columnNames[2]="Nazwisko";
		for (int j=3;j<columns+3;j++){
		columnNames[j]="";
		}
		    
	    if(tab==0){
	    	String text = "select imie, nazwisko from uczen where id=";
	    	ResultSet rs;
	    	try{
	    		for (int i=0;i<dziennik.getUczen_klasy().size();i++){
	    			Uczen_klasy uczen = dziennik.getUczen_klasy().get(i);
	    			ArrayList<Ocena> oceny = uczen.getPrzedmioty().get(przedmiot).getOceny();
	    		
	    			Object[] row = new Object[columns+3];   
	    			rs=Polaczenie.MySQL_zapytanie(text+uczen.getId());
	    			rs.next();
	    			row[0]=""+uczen.getId();
	    			row[1]=rs.getString("imie");
	    			row[2]=rs.getString("nazwisko");
	    			
	    			if (columns>0){
	    				for (int j=0;j<columns;j++){
	    					if (oceny.size()<=j) oceny.add(j,new Ocena("",0,1));
	    					row[j+3]=(Ocena)oceny.get(j);
	    				}
	    			}
					data[i] = row;
	    		}
	    	}
	    	catch (SQLException e)
			{
				e.printStackTrace();
			}
	    }
	    else if (tab==1){
	    	String text = "select imie, nazwisko from uczen where id=";
	    	ResultSet rs;
	    	try{
	    		for (int i=0;i<dziennik.getUczen_klasy().size();i++){
	    			Uczen_klasy uczen = dziennik.getUczen_klasy().get(i);
	    			ArrayList<Obecnosc> obecnosci = uczen.getPrzedmioty().get(przedmiot).getObecnosci();
	    		
	    			Object[] row = new Object[columns+3];   
	    			rs=Polaczenie.MySQL_zapytanie(text+uczen.getId());
	    			rs.next();
	    			row[0]=""+uczen.getId();
	    			row[1]=rs.getString("imie");
	    			row[2]=rs.getString("nazwisko");
	    			
	    			if (columns>0){
	    				for (int j=0;j<columns;j++){
	    					if (obecnosci.size()<=j){
	    						int dzien=calendar.get(Calendar.DAY_OF_MONTH);
	    						int miesiac=calendar.get(Calendar.MONTH);
	    						int rok=calendar.get(Calendar.YEAR);
	    						String date=""+dzien;
	    						if (dzien<10)date="0"+date+"-";
	    						else date=date+miesiac;
	    						date=date+miesiac+"-"+rok;	    						
	    						obecnosci.add(j,new Obecnosc(date,' '));
	    					}
	    					row[j+3]=(Obecnosc)obecnosci.get(j);
	    				}
	    			}
					data[i] = row;
	    		}
	    	}
	    	catch (SQLException e)
			{
				e.printStackTrace();
			}
	    }
	    else if (tab==2){
	    	String text = "select imie, nazwisko from uczen where id=";
	    	ResultSet rs;
	    	try{
	    		for (int i=0;i<dziennik.getUczen_klasy().size();i++){
	    			Uczen_klasy uczen = dziennik.getUczen_klasy().get(i);
	    			ArrayList<Uwaga> uwagi = uczen.getUwagi();
	    		
	    			Object[] row = new Object[columns+3];   
	    			rs=Polaczenie.MySQL_zapytanie(text+uczen.getId());
	    			rs.next();
	    			row[0]=""+uczen.getId();
	    			row[1]=rs.getString("imie");
	    			row[2]=rs.getString("nazwisko");
	    			
	    			if (columns>0){
	    				for (int j=0;j<columns;j++){
	    					if (uwagi.size()<=j) uwagi.add(j,new Uwaga("","",0,false,0));
	    					row[j+3]=(Uwaga)uwagi.get(j);
	    				}
	    			}
					data[i] = row;
	    		}
	    	}
	    	catch (SQLException e)
			{
				e.printStackTrace();
			}    	
	    }
    
    }    
    
    /**
	 * <p>
	 * Metoda dodajaca nowa kolumne ocen do tabeli,
	 * gdzie wartosci w nowych komorkach pobierane sa jako parametry
	 * </p> 
	 * 
	 * @param nazwa - obiekt typu String - nazwa oceny
	 * @param wartosc - obiekt typu double - wartosc oceny
	 * @param waga - obiekt typu double - wartosc oceny
	 */
    public void addOcenaColum(String nazwa, double wartosc, int waga){
   		Object data_new[][] = new Object[rows][columns+1+3];
   		String columnNames_new[]=new String[columns+1+3];
   		for (int i=0; i<=columns+3;i++){
   			for (int j=0;j<rows;j++){
   				if (i<columns+3){
   					data_new[j][i]=data[j][i];
   				}
   				else{
   					Ocena ocena = new Ocena(nazwa,wartosc,waga);
   					data_new[j][i]=ocena;
   				}
   			}
   			if (i<columns+3){
   				columnNames_new[i] = columnNames[i];			
   			}
   		}				
   		columnNames_new[columns+3]="";
   		columns++;
   		this.columnNames=columnNames_new;
   		this.data=data_new;
   		this.fireTableStructureChanged();
    }
    
    /**
	 * <p>
	 * Metoda dodajaca nowa kolumne obecnosci do tabeli,
	 * gdzie wartosci w nowych komorkach pobierane sa jako parametry
	 * </p> 
	 * 
	 * @param date - obiekt typu String - data obecnosci
	 * @param rodzaj - obiekt typu char - rodzaj oceny
	 */
    public void addObecnoscColum(String date, char rodzaj){
   		Object data_new[][] = new Object[rows][columns+1+3];
   		String columnNames_new[]=new String[columns+1+3];
   		for (int i=0; i<=columns+3;i++){
   			for (int j=0;j<rows;j++){
   				if (i<columns+3){
   					data_new[j][i]=data[j][i];
   				}
   				else{
   					Obecnosc obecnosc = new Obecnosc(date, rodzaj);
   					data_new[j][i]=obecnosc;
   				}
   			}
   			if (i<columns+3){
   				columnNames_new[i] = columnNames[i];			
   			}
   		}				
   		columnNames_new[columns+3]="";
   		columns++;
   		this.columnNames=columnNames_new;
   		this.data=data_new;
   		this.fireTableStructureChanged();
    }
    
    /**
	 * <p>
	 * Metoda dodajaca nowa kolumne uwag do tabeli,
	 * gdzie wartosci w nowych komorkach pobierane sa jako parametry
	 * </p> 
	 * 
	 * @param tresc - obiekt typu String - tresc uwagi
	 * @param date - obiekt typu String - data uwagi
	 * @param wystawiajacy - obiekt typu int - wystawiajacy uwage
	 * @param przeczytano - obiekt typu boolean - mowi o tym czy uwage przeczytano
	 * @param przedmiot - obiekt typu int - przedmiot na ktorym wystawiono uwage
	 */
    public void addUwagaColum(String tresc, String date, int wystawiajacy, boolean przeczytano, int przedmiot){
   		Object data_new[][] = new Object[rows][columns+1+3];
   		String columnNames_new[]=new String[columns+1+3];
   		for (int i=0; i<=columns+3;i++){
   			for (int j=0;j<rows;j++){
   				if (i<columns+3){
   					data_new[j][i]=data[j][i];
   				}
   				else{
   					Uwaga uwaga = new Uwaga(tresc, date, wystawiajacy, przeczytano, przedmiot);
   					data_new[j][i]=uwaga;
   				}
   			}
   			if (i<columns+3){
   				columnNames_new[i] = columnNames[i];			
   			}
   		}				
   		columnNames_new[columns+3]="";
   		columns++;
   		this.columnNames=columnNames_new;
   		this.data=data_new;
   		this.fireTableStructureChanged();
    }
    
    /**
	 * <p>
	 * Metoda zapisujaca zmiany wprowadzone w dzienniku
	 * przez edycje w trbie nauczyciela.
	 * </p> 
	 * @return Metoda zwraca zaktualizowany obiekt dziennika
	 */
    public Dziennik zapiszZmianyDziennika(){
    	if (tab==0){    		
	    	for (int i=0;i<dziennik.getUczen_klasy().size();i++){//dla kazdego ucznia klasy
	    		ArrayList<Ocena> oceny = new ArrayList<Ocena>();
	    		for (int j=3;j<columns+3;j++){
	    			oceny.add((Ocena)data[i][j]);
	    		}
	    		dziennik.getUczen_klasy().get(i).getPrzedmioty().get(przedmiot).setOceny(oceny);
	    	}
    	}
    	else if (tab==1){
	    	for (int i=0;i<dziennik.getUczen_klasy().size();i++){//dla kazdego ucznia klasy
	    		ArrayList<Obecnosc> obecnosci = new ArrayList<Obecnosc>();
	    		for (int j=3;j<columns+3;j++){
	    			obecnosci.add((Obecnosc)data[i][j]);
	    		}
	    		dziennik.getUczen_klasy().get(i).getPrzedmioty().get(przedmiot).setObecnosci(obecnosci);
	    	}
    	}
    	else if (tab==2){
	    	for (int i=0;i<dziennik.getUczen_klasy().size();i++){//dla kazdego ucznia klasy
	    		ArrayList<Uwaga> uwagi = new ArrayList<Uwaga>();
	    		for (int j=3;j<columns+3;j++){
	    			uwagi.add((Uwaga)data[i][j]);
	    		}
	    		dziennik.getUczen_klasy().get(i).setUwagi(uwagi);
	    	}
    	}
    	return dziennik;
    }
    
    /**
	 * <p>
	 * Metoda usuwajaca wybrana kolumne z tabeli.
	 * </p> 
	 * 
	 * @param column - obiekt typu int - definiuje ktora kolumna ma zostac usunieta
	 */
    public void removeColumn(int column){
   		Boolean remove=true;
   		if (column<this.columns+3){
    		if (tab==3){//sprawdzanie czy kolumna jest pusta
	    		for (int i=0;i<data.length;i++){
	    			if (data[i][column].toString().length()>0) remove=false;
	    		}
    		}
    		if (remove){
	       		Object data_new[][] = new Object[data.length][columns-1+3];
	       		String columnNames_new[]=new String[columns-1+3];
	       		int it=0;
	       		for (int i=0; i<columns+3;i++){
	       			for (int j=0;j<rows;j++){
	       				if (i!=column){
	       					data_new[j][it]=data[j][i];
	      				}
	       			}
	       			if (i!=column){
	       			columnNames_new[it] = columnNames[i];	
	       			it++;
	       			}
	       		}
	       		columns--;
	       		this.columnNames=columnNames_new;
	       		this.data=data_new;
	       		this.fireTableStructureChanged();
    		}
   		}
    }
    
    /**
	 * <p>
	 * Metoda zwraca ilosc kolumn w tabeli
	 * </p> 
	 * @return Metoda zwraca ilosc kolumn w tabeli
	 */
    public int getColumnCount() {
        return columns+3;
    }

    /**
	 * <p>
	 * Metoda zwraca ilosc wierszy w tabeli
	 * </p> 
	 * @return Metoda zwraca ilosc wierszy w tabeli
	 */
    public int getRowCount() {
        return data.length;
    }

    /**
	 * <p>
	 * Metoda zwraca nazwe kolumny
	 * </p> 
	 * @return Metoda zwraca nazwe kolumny
	 */
    public String getColumnName(int col) {
        return columnNames[col];
    }

    /**
	 * <p>
	 * Metoda zwraca obiekt znajdujacy sie
	 * w zadanej parametrami komorce tabeli
	 * </p> 
	 * @return Metoda zwraca obiekt klasy Object
	 */
    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    /**
	 * <p>
	 * Metoda zwraca klase obiektow przechowywanych w danej komorce
	 * </p> 
	 * @return Metoda zwraca obiekt typu Class
	 */
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /**
	 * <p>
	 * Metoda zwraca zawsze false, gdyz tabele sa nieedytowalne
	 * </p> 
	 * @return Metoda zawsze zwraca false
	 */
    public boolean isCellEditable(int row, int col) {
    	return false;
    }

    /**
	 * <p>
	 * Metoda zapisujaca obiekt do tabeli w podane przez parametry row i col komorce,
	 * oraz powoduje aktualizacje wygladu tabeli
	 * </p>
	 * @param value - obiekt klasy Object - wartosc przechowywana w komorce tabeli
	 * @param row - obiekt typu int - wiersz tabeli
	 * @param col - obiekt typu int - kolumna tabeli
	 */
    public void setValueAt(Object value, int row, int col) {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }
}
